package org.dtrd.modules.shop.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.dtrd.config.pay.OrderUtil;
import org.dtrd.config.pay.PayConstant;
import org.dtrd.config.pay.PayConstant.OrderStatus;
import org.dtrd.config.pay.PayConstant.OrderType;
import org.dtrd.config.pay.PayConstant.PayStatus;
import org.dtrd.config.system.Constant.QRCODE_TYPE;
import org.dtrd.config.wechat.api.impl.WechatApi;
import org.dtrd.config.wechat.entity.bean.WechatQrCodeTicket;
import org.dtrd.modules.achievement.entity.bean.SigninTemplateListInfo;
import org.dtrd.modules.message.util.MsgEventPusher;
import org.dtrd.modules.patient.entity.po.DtrdEntRdFlupRecord;
import org.dtrd.modules.patient.entity.po.DtrdEntRdPatient;
import org.dtrd.modules.patient.service.IDtrdEntRdPatientService;
import org.dtrd.modules.service.entity.bean.PackageSpecs;
import org.dtrd.modules.service.entity.bean.ServicePackage;
import org.dtrd.modules.service.entity.po.DtrdEntRdServicePackage;
import org.dtrd.modules.service.service.IDtrdEntRdServicePackageService;
import org.dtrd.modules.service.service.IDtrdEntRdServicePackageSpecsService;
import org.dtrd.modules.shop.entity.bean.*;
import org.dtrd.modules.shop.entity.po.DtrdEntShcRdOrder;
import org.dtrd.modules.shop.entity.po.DtrdEntShcRdOrderJoinProduct;
import org.dtrd.modules.shop.entity.po.DtrdEntShcRdProduct;
import org.dtrd.modules.shop.mapper.DtrdEntShcRdOrderMapper;
import org.dtrd.modules.shop.service.IDtrdEntShcRdOrderJoinProductService;
import org.dtrd.modules.shop.service.IDtrdEntShcRdOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dtrd.modules.util.NumberUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.dynamic.datasource.annotation.DS;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import javax.annotation.Nonnull;
import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 订单记录表 服务实现类
 * </p>
 *
 * @author xiao
 * @since 2022-06-06
 */
@DS("multi-datasource1")
@Service
@Slf4j
public class DtrdEntShcRdOrderServiceImpl extends ServiceImpl<DtrdEntShcRdOrderMapper, DtrdEntShcRdOrder> implements IDtrdEntShcRdOrderService {

    @Autowired
    private IDtrdEntRdServicePackageService servicePackageService;
    @Autowired
    private IDtrdEntRdServicePackageSpecsService servicePackageSpecsService;
    @Autowired
    private IDtrdEntRdPatientService patientService;
    @Autowired
    private IDtrdEntShcRdOrderJoinProductService orderJoinProductService;

    @Autowired
    private WechatApi wechatApi;

    @Autowired
    private MsgEventPusher msgEventPusher;

    @Override
    public List<OrderListInfo> getOrderList(OrderListRequest request) {
        LambdaQueryWrapper<DtrdEntShcRdOrder> queryWrapper = baseQueryWrapper();
        if (request.getPatientId() != null) {
            queryWrapper.eq(DtrdEntShcRdOrder::getOrderInfoUserid, request.getPatientId());
        }
        List<DtrdEntShcRdOrder> poList = list(queryWrapper);
        List<OrderListInfo> dtoList = new ArrayList<>(poList.size());
        if (!poList.isEmpty()) {
            dtoList = poList.stream().map(po -> {
                OrderListInfo orderListInfo = new OrderListInfo(po);
                if (po.getOrderInfoOrderstatus() != null) {
                    orderListInfo.setOrderInfoOrderstatusText(PayConstant.OrderStatus.valueOf(po.getOrderInfoOrderstatus()).getName());
                }
                return orderListInfo;
            }).collect(Collectors.toList());
        }
        return dtoList;
    }

    @Override
    public IPage<OrderListInfo> pageOrder(OrderPageRequest request) {
        LambdaQueryWrapper<DtrdEntShcRdOrder> queryWrapper = baseQueryWrapper();
        IPage<DtrdEntShcRdOrder> page = new Page<>(request.getPageNum(), request.getPageSize());
        page = this.page(page, queryWrapper);
        return page.convert(OrderListInfo::new);
    }

    @Override
    public IPage<OrderListInfo> omsPageOrder(OrderOmsPageRequest request) {
        LambdaQueryWrapper<DtrdEntShcRdOrder> queryWrapper = baseQueryWrapper();
        queryWrapper.eq(DtrdEntShcRdOrder::getOrgCode, request.getOrgCode());
        if (request.getOrderProductCategory() != null && request.getOrderProductCategory() != 0) {
            queryWrapper.eq(DtrdEntShcRdOrder::getOrderInfoProductCategory, request.getOrderProductCategory());
        }
        if (request.getOrderStatus() != null) {
            queryWrapper.eq(DtrdEntShcRdOrder::getOrderInfoOrderstatus, request.getOrderStatus());
        }
        if (request.getPatientId() != null) {
            queryWrapper.eq(DtrdEntShcRdOrder::getOrderInfoUserid, request.getPatientId());
        }
        if (request.getPayStatus() != null) {
            queryWrapper.eq(DtrdEntShcRdOrder::getOrderInfoPaystatus, request.getPayStatus());
        }
        queryWrapper.orderByDesc(DtrdEntShcRdOrder::getCreateTime);
        IPage<DtrdEntShcRdOrder> page = new Page<>(request.getPageNum(), request.getPageSize());
        page = this.page(page, queryWrapper);
        return page.convert(po -> {
            OrderListInfo orderListInfo = new OrderListInfo(po);
            DtrdEntRdPatient patient = patientService.getById(po.getOrderInfoUserid());
            if (patient != null) {
                orderListInfo.setPatientName(patient.getPatientsName());
                orderListInfo.setPatientAvatar(patient.getPatientsImg());
                orderListInfo.setPatientMobile(patient.getPatientsMobile());
            }
            if (po.getOrderInfoOrderstatus() != null) {
                orderListInfo.setOrderInfoOrderstatusText(PayConstant.OrderStatus.valueOf(po.getOrderInfoOrderstatus()).getName());
            }

            List<DtrdEntShcRdOrderJoinProduct> orderProducts = orderJoinProductService.list(
                    Wrappers.lambdaQuery(DtrdEntShcRdOrderJoinProduct.class)
                    .eq(DtrdEntShcRdOrderJoinProduct::getOrderId, po.getDataId())
            );
            orderListInfo.setOrderInfoProducts(orderProducts);

            return orderListInfo;
        });
    }

    @Override
    public OrderDetail getOrder(Integer dataId) {
        DtrdEntShcRdOrder dtrdEntShcRdOrder = getById(dataId);
        return Optional.ofNullable(dtrdEntShcRdOrder)
                .map(po -> new OrderDetail().parseFromPo(po))
                .orElse(null);
    }

    @Override
    public boolean saveOrUpdateOrder(OrderDetail dto) {
        DtrdEntShcRdOrder dtrdEntShcRdOrder = new DtrdEntShcRdOrder();
        if (dto.getDataId() == null) {
            dtrdEntShcRdOrder = dtrdEntShcRdOrder.init();
        }
        dtrdEntShcRdOrder.parseFromDto(dto);
        return saveOrUpdate(dtrdEntShcRdOrder);
    }

    @Override
    public boolean removeOrder(Integer dataId) {
        return removeById(dataId);
    }

    @Override
    public DtrdEntShcRdOrder createServiceOrder(@Nonnull Integer patientId, @Nonnull Integer serviceId, String serviceSpec, @Nonnull Integer orderType) {
        DtrdEntRdServicePackage servicePackage = servicePackageService.getById(serviceId);
        log.info("DtrdEntShcRdOrderServiceImpl.createServiceOrder.[patientId, serviceId, orderType] serviceId=" + serviceId + "; servicePackage=" + servicePackage);
        if (servicePackage == null) {
            return null;
        }
        Integer discount = servicePackage.getPackageDiscount();
        ServicePackage sp = servicePackageSpecsService.getServicePackageSpecsInfo(serviceId, discount);
        Long price = null;
        String title = servicePackage.getPackageName();
        if (sp != null) {
            List<PackageSpecs> specsList = sp.getPackageSpecs();
            if (CollectionUtil.isNotEmpty(specsList)) {
                for (PackageSpecs spec : specsList) {
                    if (Objects.equals(spec.getName(), serviceSpec)) {
                        discount = spec.getPrice();
                        title += "-" + spec.getName();
                        break;
                    }
                }
            }
        }
        if (discount != null) {
            log.info("DtrdEntShcRdOrderServiceImpl.createServiceOrder.[patientId, serviceId, orderType] discount=" + discount + "; OrderUtil.changeY2F(discount)=" + OrderUtil.changeY2F(discount + 0.0f));
            price = Long.valueOf(discount);
        }
        if (price == null) {
            price = 1L;
        }
        log.info("DtrdEntShcRdOrderServiceImpl.createServiceOrder.[patientId, serviceId, orderType] price=" + price);
        DtrdEntShcRdOrder order = new DtrdEntShcRdOrder().init();
        order.setOrderInfoSum(price);
        order.setOrderInfoTitle(title);
        order.setOrderInfoNo(OrderUtil.generateOrderNo(patientId, orderType));
        order.setOrderInfoServiceId(serviceId);
        order.setOrderInfoUserid(patientId);
        order.setOrderInfoType(OrderType.SERVICE.getType());
        save(order);
        return order;
    }

    @Override
    public DtrdEntShcRdOrder getServiceOrderByPatientIdServiceId(Integer patientId, Integer serviceId, Integer orderType) {
        LambdaQueryWrapper<DtrdEntShcRdOrder> wrapper = baseQueryWrapper();
        wrapper.eq(DtrdEntShcRdOrder::getOrderInfoUserid, patientId)
                .eq(DtrdEntShcRdOrder::getOrderInfoServiceId, serviceId)
                .eq(DtrdEntShcRdOrder::getOrderInfoType, orderType);
        return getOne(wrapper);
    }

    @Override
    public void updateOrderStatus(String orderDataId, int userId, int payStatus, int orderStatus, int payType, String transactionId) {
        DtrdEntShcRdOrder order = getById(orderDataId);
        order.setOrderInfoPaystatus(payStatus);
        order.setOrderInfoPayType(payType);
        if (payStatus == PayStatus.PAYED.getState()) {
            order.setPayTime(new Date());
            // 支付完成时生成二维码，发送支付完成通知
            Map<String, String> others = new HashMap<>(2);
            others.put("orderId", orderDataId);
            others.put("payType", payType + "");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("orderId", orderDataId);
            jsonObject.put("payType", payType + "");
            WechatQrCodeTicket qrCode = wechatApi.createUserQrCode(null, QRCODE_TYPE.ORDER.getType(), orderDataId);
            log.info("DtrdEntShcRdOrderServiceImpl.updateOrderStatus.[orderDataId, userId, payStatus, orderStatus, payType] qrCode=" + qrCode);
            if (qrCode != null) {
                log.info("DtrdEntShcRdOrderServiceImpl.updateOrderStatus.[orderDataId, userId, payStatus, orderStatus, payType] qrCode=" + qrCode);
                order.setOrderInfoQrcode(qrCode.getQrCodeUrl());
                order.setOrderInfoQrcodeResult(qrCode.getUrl());
            }
            // 发送支付完成通知
            msgEventPusher.sendOrderPaySuccessMsg(userId, orderDataId, order.getOrderInfoSum(), order.getOrderInfoTitle(), order.getOrderInfoNo(), order.getPayTime());
        }
        order.setOrderInfoOrderstatus(orderStatus);
        order.setTransactionId(transactionId);
        updateById(order);
    }

    @Override
    public boolean completeOrder(String orderId) {
        DtrdEntShcRdOrder order = getById(orderId);
        if (order != null) {
            order.setCompleteTime(new Date());
            order.setOrderInfoOrderstatus(OrderStatus.COMPLETE.getState());
            return updateById(order);
        }
        return false;
    }

    private LambdaQueryWrapper<DtrdEntShcRdOrder> baseQueryWrapper() {
        return Wrappers.lambdaQuery(DtrdEntShcRdOrder.class)
                .eq(DtrdEntShcRdOrder::getIsDel, 0);
    }

    private LambdaUpdateWrapper<DtrdEntShcRdOrder> baseUpdateWrapper() {
        return Wrappers.lambdaUpdate(DtrdEntShcRdOrder.class)
                .eq(DtrdEntShcRdOrder::getIsDel, 0);
    }
}
